package com.superhelper.common.service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.push.model.v20160801.PushRequest;
import com.aliyuncs.push.model.v20160801.PushResponse;
import com.aliyuncs.utils.ParameterHelper;
import com.superhelper.common.Consts;
import com.superhelper.common.domain.ExtMsg;
import com.superhelper.common.mapper.UserMapper;
import com.superhelper.common.utils.JsonHelper;

public class AliYunPushService {
    private final static Logger LOG = LoggerFactory.getLogger(AliYunPushService.class);
    // private final Long appKey = 24540701L;
    private final String region = "cn-hangzhou";
    private final String accessKeyId = "LTAIayggS1c9jA2q";
    private final String accessKeySecret = "u7XDsuMBjLvkzdn3o6Sct7PhEQQ5Kw";
    @Value("${online}")
    private Boolean online = false;
    @Autowired
    private UserMapper userMapper;
    private DefaultAcsClient client;
    @SuppressWarnings("serial")
    private Map<String, Long> appKeyMap = new HashMap<String, Long>() {
        {
            put("com.superhelper", 24540701L); // 完整版
            put("com.superhelper.superaide", 24584729L); // 简化版
        }
    };

    public AliYunPushService() {
        IClientProfile profile = DefaultProfile.getProfile(region, accessKeyId, accessKeySecret);
        client = new DefaultAcsClient(profile);
    }

    public boolean push(String title, String content, String device, final String target, ExtMsg msg) {
        LOG.info("[push] target:{},title:{},content:{},{}", target, title, content, msg);

        Long appKey = getAppKey(target);
        PushRequest pushRequest = new PushRequest();
        // 安全性比较高的内容建议使用HTTPS
        pushRequest.setProtocol(ProtocolType.HTTPS);
        // 内容较大的请求，使用POST请求
        pushRequest.setMethod(MethodType.POST);
        // 推送目标
        pushRequest.setAppKey(appKey);
        pushRequest.setTarget("ACCOUNT"); // 推送目标: DEVICE:按设备推送 ALIAS : 按别名推送
        // ACCOUNT:按帐号推送 TAG:按标签推送; ALL:
        // 广播推送
        pushRequest.setTargetValue(target); // 根据Target来设定，如Target=DEVICE,
        // 则对应的值为 设备id1,设备id2.
        // 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
        // pushRequest.setTarget("ALL"); //推送目标: device:推送给设备;
        // account:推送给指定帐号,tag:推送给自定义标签; all: 推送给全部
        // pushRequest.setTargetValue("ALL"); //根据Target来设定，如Target=device,
        // 则对应的值为 设备id1,设备id2. 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
        pushRequest.setPushType("MESSAGE"); // 消息类型 MESSAGE NOTICE
        pushRequest.setDeviceType("ANDROID"); // 设备类型 ANDROID iOS ALL.
        // 推送配置
        pushRequest.setTitle(title); // 消息的标题
        pushRequest.setBody(msg.toString()); // 消息的内容
        if (StringUtils.containsIgnoreCase(device, Consts.Device.IOS)) {
            pushRequest.setDeviceType("iOS");
            // 推送配置: iOS
            String osMusic = this.getoSMusic(msg);
            pushRequest.setiOSBadge(5); // iOS应用图标右上角角标
            pushRequest.setiOSSilentNotification(false);// 开启静默通知
            pushRequest.setiOSMusic(osMusic); // iOS通知声音
            pushRequest.setiOSSubtitle(title);// iOS10通知副标题的内容
            pushRequest.setiOSNotificationCategory("外卖助手");// 指定iOS10通知Category
            pushRequest.setiOSMutableContent(true);// 是否允许扩展iOS通知内容
            if (online) {
                pushRequest.setiOSApnsEnv("PRODUCT");// iOS的通知是通过APNs中心来发送的，需要填写对应的环境信息。"DEV"
                // : 表示开发环境 "PRODUCT" : 表示生产环境
            } else {
                pushRequest.setiOSApnsEnv("DEV");// iOS的通知是通过APNs中心来发送的，需要填写对应的环境信息。"DEV"
                // : 表示开发环境 "PRODUCT" : 表示生产环境
            }
            pushRequest.setiOSRemind(true); // 消息推送时设备不在线（既与移动推送的服务端的长连接通道不通），则这条推送会做为通知，通过苹果的APNs通道送达一次。注意：离线消息转通知仅适用于生产环境
            pushRequest.setiOSRemindBody(content);// iOS消息转通知时使用的iOS通知内容，仅当iOSApnsEnv=PRODUCT
            // && iOSRemind为true时有效
            pushRequest.setiOSExtParameters(msg.toString());
        }

        // 推送控制
        // Date pushDate = new Date(System.currentTimeMillis() + 5 * 1000); //
        // 延迟5秒推送,
        // 也可以设置成你指定固定时间
        // String pushTime = ParameterHelper.getISO8601Time(pushDate);
        // pushRequest.setPushTime(pushTime); // 延后推送。可选，如果不设置表示立即推送
        String expireTime = ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 1 * 3600 * 1000)); // 1小时后消息失效,
        // 不会再发送
        pushRequest.setExpireTime(expireTime);
        pushRequest.setStoreOffline(true); // 离线消息是否保存,若保存,
        try {
            LOG.info("push pushRequest:{}", JsonHelper.toJson(pushRequest));
            PushResponse pushResponse = client.getAcsResponse(pushRequest);
            LOG.info("push RequestId:{},MessageID:{}-{}", pushResponse.getRequestId(), pushResponse.getMessageId(), msg);
            return true;
        } catch (ClientException e) {
            // TODO Auto-generated catch block
            LOG.error("push pushRequest error:{},", e);
        }
        return false;
    }

    public boolean sendToUser(String title, String content, final String target, ExtMsg extras) {
        LOG.info("[sendToUser]title:{},content:{},target:{},extras:{}", title, content, target, extras);
        Long appKey = getAppKey(target);
        PushRequest pushRequest = new PushRequest();
        // 安全性比较高的内容建议使用HTTPS
        pushRequest.setProtocol(ProtocolType.HTTPS);
        // 内容较大的请求，使用POST请求
        pushRequest.setMethod(MethodType.POST);
        // 推送目标
        pushRequest.setAppKey(appKey);
        pushRequest.setTarget("ALIAS"); // 推送目标: DEVICE:按设备推送 ALIAS : 按别名推送
        // ACCOUNT:按帐号推送 TAG:按标签推送; ALL:
        // 广播推送
        pushRequest.setTargetValue(target); // 根据Target来设定，如Target=DEVICE,
        // 则对应的值为 设备id1,设备id2.
        // 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
        // pushRequest.setTarget("ALL"); //推送目标: device:推送给设备;
        // account:推送给指定帐号,tag:推送给自定义标签; all: 推送给全部
        // pushRequest.setTargetValue("ALL"); //根据Target来设定，如Target=device,
        // 则对应的值为 设备id1,设备id2. 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
        pushRequest.setPushType("MESSAGE"); // 消息类型 MESSAGE NOTICE
        pushRequest.setDeviceType("ALL"); // 设备类型 ANDROID iOS ALL.

        // 推送配置
        pushRequest.setTitle(title); // 消息的标题
        pushRequest.setBody(extras.toString()); // 消息的内容

        // 推送配置: iOS
        pushRequest.setiOSBadge(1); // iOS应用图标右上角角标
        pushRequest.setiOSSilentNotification(false);// 开启静默通知
        pushRequest.setiOSMusic("default"); // iOS通知声音
        pushRequest.setiOSSubtitle(title);// iOS10通知副标题的内容
        pushRequest.setiOSNotificationCategory("iOS10 Notification Category");// 指定iOS10通知Category
        pushRequest.setiOSMutableContent(true);// 是否允许扩展iOS通知内容
        if (online) {
            pushRequest.setiOSApnsEnv("PRODUCT");// iOS的通知是通过APNs中心来发送的，需要填写对应的环境信息。"DEV"
            // : 表示开发环境 "PRODUCT" : 表示生产环境
        } else {
            pushRequest.setiOSApnsEnv("DEV");// iOS的通知是通过APNs中心来发送的，需要填写对应的环境信息。"DEV"
            // : 表示开发环境 "PRODUCT" : 表示生产环境
        }
        pushRequest.setiOSRemind(true); // 消息推送时设备不在线（既与移动推送的服务端的长连接通道不通），则这条推送会做为通知，通过苹果的APNs通道送达一次。注意：离线消息转通知仅适用于生产环境
        pushRequest.setiOSRemindBody(content);// iOS消息转通知时使用的iOS通知内容，仅当iOSApnsEnv=PRODUCT
        // && iOSRemind为true时有效
        pushRequest.setiOSExtParameters(extras.toString());
        String expireTime = ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 1 * 3600 * 1000)); // 1小时后消息失效,
        pushRequest.setExpireTime(expireTime);
        pushRequest.setStoreOffline(true); // 离线消息是否保存,若保存,
        try {
            LOG.info("sendToUser pushRequest:{},", JsonHelper.toJson(pushRequest));
            PushResponse pushResponse = client.getAcsResponse(pushRequest);
            LOG.info("sendToUser RequestId:{},MessageID:{}", pushResponse.getRequestId(), pushResponse.getMessageId());
            return true;
        } catch (ClientException e) {
            // TODO Auto-generated catch block
            LOG.error("sendToUser pushRequest error:{},", e);
        }
        return false;
    }

    // 消息语音文件名
    private String getoSMusic(ExtMsg msg) {
        String audioType = msg.getMsgAttr("type") + "";
        String shop_type = msg.getMsgAttr("shop_type") + "";
        String oSMusic = "default";
        if (StringUtils.isNoneBlank(audioType)) {
            oSMusic = audioType + "_" + shop_type + ".mp3";
        }
        return oSMusic;
    }

    /**
     * 根据imid,获取推送appKey
     * 
     * @param imid
     * @return
     */
    private Long getAppKey(String imid) {
        String packageName = userMapper.getPackageNameByImid(imid);
        if (StringUtils.isBlank(packageName)) {
            return 24540701L;
        } else {
            return appKeyMap.get(packageName);
        }
    }

    public static void main(String args[]) {
        AliYunPushService a = new AliYunPushService();
        String target = "0bc053151780181deb41d9de3d3375e8";
        String title = "新消息";
        Map<String, Object> msgMap = new HashMap<>();
        msgMap.put("orderId", 2745);
        msgMap.put("type", "deliver_expire");
        msgMap.put("shop_type", "ele");
        msgMap.put("book", false);
        ExtMsg msg = new ExtMsg("order", msgMap);
        a.push(title, title, "android", target, msg);

        // Map<String, Object> msgMap1 = new HashMap<>();
        // msgMap1.put("userId", 8);
        // msgMap1.put("type", "on_line");
        // msgMap1.put("uuid", "326F950D-8286-48D5-A4F2-8351CDFE1719");
        // ExtMsg msg1 = new ExtMsg("user", msgMap1);
        // String title1 = "新消息";
        // a.push(title1, title1, target, msg1);

    }
}
